#include "FileSystem.h"
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
struct FileSystem
{
    char *dirPath;
};

struct PacketFile
{
    FILE *f;
    long FileSize;
    long currentPosition;
};

FileSys *FileSystemInit(const char *DirPath)
{
    FileSys *fs = (FileSys *)malloc(sizeof(DirPath));
    if (fs == NULL)
    {
        printf("FileSystemInit malloc error!\n");
    }

    DIR *dir;
    if ((dir = opendir(DirPath)) == NULL)
    {
        if (mkdir(DirPath, 0777) != 0)
        {
            perror("mkdir");
            free(fs);
            return NULL;
        }
        fs->dirPath = strdup(DirPath);
        return fs;
    }
    else
    {
        closedir(dir);
        fs->dirPath = strdup(DirPath);
        return fs;
    }
}

bool CreateNewDirInFs(FileSys *fs, const char *DirName)
{
    char DirPath[1024] = {0};
    sprintf(DirPath, "%s/%s", fs->dirPath, DirName);
    if (mkdir(DirPath, 0777) != 0)
    {
        perror("mkdir");
        return false;
    }
    return true;
}

bool DeleteDirInFs(FileSys *fs, const char *DirName)
{
    char DirPath[1024] = {0};
    sprintf(DirPath, "%s/%s", fs->dirPath, DirName);
    if (rmdir(DirPath) != 0)
    {
        perror("rmdir");
        return false;
    }
    return true;
}

void WriteFileToFs(FileSys *fs, const char *DirName, const char *fileName, void *p, size_t size)
{
    char filePath[1024] = {0};
    sprintf(filePath, "%s/%s/%s", fs->dirPath, DirName, fileName);
    FILE *f = fopen(filePath, "a");
    fwrite(p, size, 1, f);
    fclose(f);
}

bool isDirExist(FileSys *fs, const char *DirName)
{
    DIR *dir = opendir(fs->dirPath);
    if (dir == NULL)
    {
        perror("isDirExist opendir");
        return false;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL)
    {
        if (strcmp(entry->d_name, DirName) == 0)
        {
            closedir(dir);
            return true;
        }
    }
    closedir(dir);
    return false;
}

char *GetFileSize(const char *DirPath, const char *fileName)
{
    char filePath[1024] = {0};
    sprintf(filePath, "%s/%s", DirPath, fileName);

    struct stat st;
    stat(filePath, &st);

    char size[20] = {0};
    sprintf(size, "%ld", st.st_size); // ld转成字符串
    return strdup(size);
}

char *GetFileList(FileSys *fs, const char *DirName)
{
    char list[1024] = {0};
    char DirPath[1024] = {0};
    sprintf(DirPath, "%s/%s", fs->dirPath, DirName);
    DIR *dir = opendir(DirPath);
    if (dir == NULL)
    {
        return NULL;
    }
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL)
    {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
            continue;

        char *size = GetFileSize(DirPath, entry->d_name);
        strcat(list, entry->d_name);
        strcat(list, ";");
        strcat(list, size);
        strcat(list, ",");
        free(size);
    }
    if (strlen(list) == 0)
        return NULL;
    list[strlen(list) - 1] = '\0';
    closedir(dir);
    return strdup(list);
}

bool IsFileExist(FileSys *fs, const char *DirName, const char *FileName)
{
    char DirPath[1024] = {0};
    sprintf(DirPath, "%s/%s", fs->dirPath, DirName);
    DIR *dir = opendir(DirPath);
    if (dir == NULL)
    {
        perror("opendir");
        return false;
    }
    else
    {
        struct dirent *entry;
        while ((entry = readdir(dir)) != NULL)
        {
            if (strcmp(entry->d_name, FileName) == 0)
            {
                closedir(dir);
                return true;
            }
        }
        closedir(dir);
        return false;
    }
}

PackFile *PacketFileInit(const char *filePath)
{
    PackFile *pf = (PackFile *)malloc(sizeof(PackFile));
    if (pf == NULL)
    {
        printf("PacketFileInit malloc error\n");
        return NULL;
    }

    pf->f = fopen(filePath, "r"); // 以最小权限发送
    if (pf->f == NULL)
    {
        printf("打开|%s|文件失败\n", filePath);
        free(pf);
        return NULL;
    }

    fseek(pf->f, 0, SEEK_END);
    pf->FileSize = ftell(pf->f);
    fseek(pf->f, 0, SEEK_SET);

    pf->currentPosition = 0;
    printf("文件大小：%ld,文件位置：%ld\n", pf->FileSize, pf->currentPosition);

    return pf;
}

void ReadFromFile(PackFile *f, void *p, int *size)
{
    if (*size + f->currentPosition > f->FileSize)
    {
        *size = f->FileSize - f->currentPosition;
    }
    fread(p, *size, 1, f->f);
    f->currentPosition += *size;
}

bool IsFileEnd(PackFile *f)
{
    return f->currentPosition == f->FileSize;
}

void ClearPacketFile(PackFile *f)
{
    fclose(f->f);
    free(f);
}


char *GetServerFileDirPath(FileSys *fs, const char *username, const char *filename)
{
    char filePath[32] = {0};
    sprintf(filePath,"%s/%s/%s",fs->dirPath,username,filename);
    return strdup(filePath);
}